home *** CD-ROM | disk | FTP | other *** search
-
- The QEMM Programming Interface - QPI
-
- Quarterdeck Technical Note #292 Filename: QPI.TEC
- by Quarterdeck Development CompuServe: QPI.TEC
- Last Revised: 04/05/95 Category: QEMM
-
- Subject: A discussion on programming issues when interfacing
- with QEMM.
-
-
- QPI:The QEMM Programming Interface
-
- The QEMM Programming Interface (QPI) lets programs request
- information or services from QEMM. Programs can use the QPI to do
- the following:
-
- Determine QEMM's status, and change that status if the system
- configuration allows;
-
- Determine QEMM's version number;
-
- Determine whether QEMM's Stealth ROM feature is active, and if so
- what Stealth ROM mode is in use;
-
- Determine the number of ROMs that QEMM is Stealthing and the
- beginning segment address and length of each ROM;
-
- Determine whether QEMM is supporting the system's Suspend/Resume
- features, and if so what interrupt these features are using;
-
- Determine whether QEMM is allowing or suppressing the BIOS calls
- that make it possible to do work while waiting for disk activity
- to complete, and tell QEMM to allow or suppress these calls if the
- system configuration allows;
-
- Copy all or part of the contents of a Stealthed ROM into a buffer;
-
- Determine the physical memory mapped to any linear memory address,
- and change the page table so that any page of physical memory is
- mapped to any linear memory address;
-
- Read or write I/O ports, even if QEMM is trapping access to those
- ports;
-
- Determine whether QEMM is trapping access to I/O ports, and tell
- QEMM to trap access to ports on the calling program's behalf;
-
- Install a software routine that performs whatever actions the
- program requires when a given I/O port is accessed;
-
- Simulate a hardware interrupt in such a way that it goes to the
- correct DESQview or DESQview/X window.
-
- You can find sample QPI code and programs on the Quarterdeck
- bulletin board and other electronic support locations.
-
- Getting the QPI Entry Point
-
- The first step in using the QPI is getting the double-word address
- of the QPI entry point.
-
- The method of obtaining the entry point address that is described
- here is available only in versions of QEMM higher than 6.00.
- Programs that want to run with QEMM 5 must use a less
- straightforward INT 2F interface to get the QPI entry point; for
- more information, contact Quarterdeck via Compuserve (GO
- QUARTERDECK), the Internet (support@qdeck.com) or our BBS and ask
- for the QDMEM interface document.
-
- QEMM defines a DOS device driver called QEMM386$. To obtain the
- entry point for QPI, do an IOCTL Read Control String call (INT 21,
- function 4402h) to read four bytes from this device driver. Here
- is a code sequence that demonstrates the details:
-
-
- QEMMDeviceName db 'QEMM386$',0
- QPIEntryPoint dd ?
-
- GetQPIEntryPoint proc
- mov dx,offset QEMMDeviceName
- mov ax,3d00h
- int 21h ; Try to open QEMM386$
- jc NoQEMM ; If CY, QEMM not present
- mov bx,ax ; Save file handle in BX
- mov dx,offset QPIEntryPoint ; Store the entry point here
- mov cx,4 ; Set up to read 4 bytes
- mov ax,4402h ; IOCTL Read Control String
- int 21h
- pushf ; Save the error code
- mov ah,3eh ; Close the handle
- int 21h
- popf ; Restore the error code
- jc NoQEMM ; If CY, QEMM is pre-6.00
- ret
- NoQEMM: stc
- ret
- GetQPIEntryPoint endp
-
-
- QPI Functions
-
- Once you have stored the address of the QPI entry point, you make
- all calls to QPI by loading AH or AX with the function number of
- the call, setting the other registers to values appropriate to the
- function, and making a far call to the entry point. The carry flag
- is set on return if there is an error, or if the function number
- is not valid in that version of QEMM.
-
- The QPI calls of interest to third-party programmers are listed
- below. The version in which each of the calls was implemented is
- noted.
-
- The QPI_GetStatus Call
-
- The QPI_GetStatus call tells you whether QEMM is on or off, and
- whether it is in auto mode (see the AUTO/ON/OFF parameter in
- Chapter 7 in the QEMM Reference Manual for more information). All
- versions of QEMM support this call.
-
-
- QPI_GetStatus EQU 0
- ; Takes AH = 0
- ; Returns AL = 0 if on
- ; AL = 1 if auto/on
- ; AL = 2 if off
- ; AL = 3 if auto/off
-
-
- The QPI_SetStatus Call
-
- The QPI_SetStatus call lets you set the status of QEMM. If QEMM is
- forced on by a parameter (like the RAM parameter) or other
- services that it provides, this call will have no effect. You
- should therefore make the QPI_GetStatus call after the
- QPI_SetStatus call to see if the first call was successful. All
- versions of QEMM support this call.
-
- QPI_SetStatus EQU 1
- ; Takes AH = 1
- ; AL = 0 if on
- ; AL = 1 if auto/on
- ; AL = 2 if off
- ; AL = 3 if auto/off
-
-
- The QPI_GetVersion Call
-
- The QPI_GetVersion call returns the QEMM version number in Binary
- Coded Decimal form in AX and BX. For instance, the call will
- return BX = 0750 (not BX = 0732) for QEMM version 7.5. All
- versions of QEMM support this call.
-
- QPI_GetVersion EQU 3
- ; Takes AH = 3
- ; Returns BH = major version (in Binary Coded Decimal)
- ; BL = minor version (in Binary Coded Decimal)
- ; AX = same as BX
-
-
-
- The QPI_GetInfo Call
-
- In QEMM version 6.00 and later, the QPI_GetInfo call returns an
- ASCII letter in CL that tells QEMM's Stealth ROM mode (if any),
- and a number in CH that tells which interrupt (not IRQ) QEMM is
- monitoring (if any) to support Suspend/Resume features. In QEMM
- version 7.00 and later, the call also returns the size of QEMM's
- disk buffer in DL and a bit map of information about the disk
- buffer in BH. Bit 1 of BH will be on if the disk buffer has
- already been used; bit 0 will be on if QEMM is buffering only INT
- 13s into the page frame (DISKBUFFRAME) and off if all INT 13s into
- nonlinear memory are being buffered (DISKBUF). Note that other
- registers are not preserved by this call.
-
-
- QPI_GetInfo EQU 1E00h
- ; Takes AX = 1E00
- ; Returns BH = xxxxxxAB
- ; where A = 1 if disk buffer has been used yet, 0 if not
- ; B = 1 if DISKBUFFRAME buffer, 0 if DISKBUF buffer
- - not valid if DL = 0
- ; BL = reserved
- ; CL = Stealth ROM type (0 for no Stealth ROM, "M"
- ; or "F" otherwise, other Stealth ROM types possible
- ; in future)
- ; CH = Suspend/Resume INT number (0 = none)
- ; DL = size of QEMM disk buffer in K (if 0, disk buffer
- ; doesn't exist)
- ; DH, DI, SI = reserved
-
- The QPI_GetStealthCount Call
-
- The QPI_GetStealthCount tells how many ROMs QEMM is Stealthing.
- QEMM versions 6.00 and later support this call.
-
-
- QPI_GetStealthCount equ 1E01h
- ; Takes AX = 1E01
- ; Returns BX = number of ROMs that are Stealthed
-
-
- The QPI_GetStealthList Call
-
- The QPI_GetStealthList call gives the same information as the
- QPI_GetStealthCount call, and also fills a buffer with information
- on the location and size of each Stealthed ROM. QEMM versions 6.00
- and later support this call.
-
-
- QPI_GetStealthList equ 1E02h
- ; Takes AX = 1E02
- ; ES:DI = buffer to hold the list of Stealthed ROMs
- ; Returns BX = number of ROMs that are Stealthed
- ; Table at ES:DI will be filled in with:
- ; dw ROM start segment
- ; dw Length of ROM in paragraphs
- ; for each ROM that is Stealthed
-
-
- The QPI_GetPTE Call
-
- The QPI_GetPTE call returns the page table entry for any logical
- page in the first 1088K of memory. In other words, if you pass
- this call the address of any page in the first 1088K of memory,
- the call will return (in an extended register) the doubleword page
- table entry for that address, which includes, among other things,
- information about which physical page of memory QEMM has mapped to
- the logical address that you provided. QEMM versions 6.00 and
- later support this call.
-
- CX should contain the number of the logical page in memory that
- you want to affect; the highest valid CX is 010F. (Page numbers
- refer to consecutive 4K sections of memory, aligned on 4K
- boundaries: that is, 0000 refers to paragraph 0000-00FF, 0001 to
- 0100-01FF, etc.) EDX (the extended DX register) should contain a
- page table entry, in the following format:
-
- Bit 0 is the Present bit. Any access to a page with this bit off
- causes a page fault.
-
- Bit 1 is the Read/Write bit. Any writing to a page with this bit
- off causes a page fault.
-
- Bit 2 is the User/Supervisor bit. Any access to this page when the
- processor is at privilege level 3 causes a page fault.
-
- Bits 3 and 4 must be 0.
-
- Bit 5 is the Accessed bit. Any read or write of the page causes
- the processor to turn on this bit.
-
- Bit 6 is the Dirty bit. Any write to the page causes the processor
- to turn on this bit.
-
- Bits 7 and 8 must be 0.
-
- Bits 9, 10, and 11 are available for systems programmer use.
-
- Bits 12 through 31 are the page number.
-
- For instance, a page table entry 000FF007 means physical page
- number 000FF (paragraph FF00-FFFF), which is not yet accessed nor
- dirty, but which is present, writable and user-accessible.
-
-
- QPI_GetPTE equ 1F00h
- ; Takes AX = 1F00
- ; CX = page number
- ; Returns EDX = page table entry for that page number
-
-
- The QPI_SetPTE Call
-
- The QPI_SetPTE call lets you set the page table entry for any
- logical page in the first 1088K of memory. In particular, this
- means that you can tell QEMM to map any 4K of memory to any
- 4K-aligned address below the 1088K mark. QEMM versions 6.00 and
- later support this call. See the section above on the QPI_GetPTE
- call for more information.
-
-
- QPI_SetPTE equ 1F01h
- ; Takes AX = 1F01
- ; CX = page number
- ; EDX = page table entry to set at that page number
-
-
- The QPI_GetVHIInfo Call
-
- The QPI_GetVHIInfo call, in conjunction with the QPI_SetVHIInfo
- call, is primarily used by disk cache developers who wish to get
- information on QEMM's safety precaution of suppressing the BIOS
- INT 15 function 90 callout. This safety precaution, known as
- VirtualHDIRQ or VHI (see the section on the VIRTUALHDIRQ:N
- parameter in Chapter 7 in the QEMM Reference Manual for more
- information), is normally in effect only when the disk interrupt
- INT 13 is being Stealthed. If you have verified that the use of
- INT 15 fn 90 in the disk cache you are developing is compatible
- with QEMM's Stealth ROM feature, you will want to tell QEMM to
- allow INT 15 function 90.
-
- The call returns flags in BL that give the VHI state. Bit 7 will
- be on whenever QEMM is Stealthing INT 13 (if INT 13 is not
- Stealthed, QEMM never suppresses INT 15 function 90); bit 0 will
- be on if QEMM is currently suppressing INT 15 function 90. Bits
- 1-6 of the VHI bit map are reserved. QEMM versions 6.00 and later
- support this call.
-
-
- QPI_GetVHIInfo equ 2000h
- ; Takes AX = 2000
- ; Returns BL = AxxxxxxB
- ; where A = 1 if VHI is being paid attention to
- ; B = 1 if VHI is currently enabled
- ; (i.e. INT 15 fn 90 is currently suppressed)
- ; x = reserved
-
- The QPI_SetVHIInfo Call
-
- The QPI_SetVHIInfo call lets you turn on or off QEMM's safety
- precaution of suppressing INT 15 function 90 whenever the disk
- interrupt INT 13 is being Stealthed. (See the section above on the
- QPI_GetVHIInfo call for more information.) To request a VHI state,
- set BL to 1 to suppress INT 15 function 90, or set BL to 0 to
- allow INT 15 fn 90. QEMM will return the previous VHI flags in BL.
- If bit 7 of the returned flags is off, then QEMM is not paying
- attention to the VHI state, and your request did not have an
- effect. QEMM versions 6.00 and later support this call.
-
-
- QPI_SetVHIInfo equ 2001h
- ; Takes AX = 2001
- ; BL = xxxxxxxB that you want (bit 7 is ignored)
- ; Returns BL = AxxxxxxB of previous VHI state;
- ; if A of output = 0, B of input was ignored
-
-
- The QPI_CopyStealthRoms Call
-
- The QPI_CopyStealthRoms call tells QEMM to copy the contents of
- part or all of a Stealthed ROM into a buffer in conventional
- memory. This is the only reliable to access the contents of a
- Stealthed ROM. QEMM versions 6.00 and later support this call.
-
-
- QPI_CopyStealthRoms equ 2100h
- ; Takes AX = 2100
- ; DS:SI = Original address of ROM to copy
- ; ES:DI = Destination address in conventional memory
- ; ECX = # of bytes to copy
- ; Returns CY if no stealth or if DS:SI not within C000-FFFF
-
-
- I/O Trapping
-
- The following calls make up the Quarterdeck QEMM I/O Trapping
- Programming Interface. This interface allows a real-mode program
- to specify I/O ports that QEMM should trap access to, as well as
- I/O callback routines that QEMM will call whenever one of these
- I/O ports is accessed. Using this interface, you can emulate
- hardware devices that are accessible via I/O ports.
-
- When QEMM traps an I/O port, all accesses of that port, whether
- input or output, are intercepted by QEMM. (QEMM traps certain I/O
- ports itself, for proper management of virtual-8086 mode.)
- Whenever an I/O port that a program has asked QEMM to trap is
- accessed, QEMM calls a real-mode I/O callback routine. The same
- callback routine is called for all trapped I/O ports.
-
- A program that wishes to trap an I/O port should:
-
- 1) Use the QPI_GetVersion call to make sure that the version of
- QEMM is 7.03 or later. Earlier versions do not support most of
- the I/O Trapping Programming Interface. Alternatively, if the
- version of QEMM does not support the call you have made, the
- call will return with the carry flag set;
-
- 2) Issue a QPI_GetPortTrap call to determine that another program
- is not already trapping the port. If another program is
- trapping the port, it is generally advisable not to install
- your port trap;
-
- 3) Get the address of the existing callback routine with the
- QPI_GetIOCallback call. Because there is only one I/O callback
- routine, and because multiple programs may request I/O
- trapping, your callback routine must jump to the previous
- callback routine whenever your routine is not interested in the
- I/O port being accessed;
-
- 4) Install its own far routine as the new callback routine, using
- the QPI_SetIOCallback call. Your callback routine will be
- passed the following information:
-
- AX = Data for output
- CX = Type of I/O (see flag bits defined below)
- DX = Port number
- IF = 0 (interrupts are disabled)
-
- When the callback routine has finished its work, it should return
- far with all registers other than CX and DX preserved. If the
- routine is called to get input from a port, AX should be modified.
- The bit-mapped word in CX contains the following information:
-
-
- IOT_Output equ 0000000000000100b
- ; bit 2 is 1 if output,
- ; 0 if input
-
-
- IOT_Word equ 0000000000001000b
- ; bit 3 is 1 if word I/O,
- ; 0 if byte I/O
-
-
- IOT_IF equ 0000001000000000b
- ; bit 9 is the same as the
- ; caller's interrupt flag
-
-
- 5) Specify which port to trap with the QPI_SetPortTrap call.
-
- If your program does not stay resident forever, it should do
- the following before exiting:
-
- 6) Use the QPI_GetIOCallback call to make sure that no one has
- installed a callback routine after yours. If a handler is
- installed after yours, you should remain resident;
-
- 7) Remove its trap with the QPI_ClearPortTrap call. This call will
- clear all traps on a particular I/O port, unless QEMM is
- trapping that port for itself, in which case QEMM's trapping
- alone will remain in effect for that port;
-
- 8) Remove its callback by using the QPI_SetIOCallback call to set
- the previously existing callback routine.
-
- The following restrictions apply to this interface:
-
- Only INs and OUTs of words or bytes are supported, not INs and
- OUTs of doublewords. Also, string I/O (the INS and OUTS
- instructions) are supported only as of QEMM version 7.5.
-
- QEMM cannot trap the I/O of VCPI protected-mode programs.
- Furthermore, because Quarterdeck's DPMI driver (QDPMI) is
- implemented as a VCPI client, QEMM cannot trap the I/O of DPMI
- clients either. Furthermore, these traps are no longer in effect
- when Microsoft Windows 386 enhanced mode is running.
-
- The following four calls allow you to bypass port trapping and
- read and write I/O ports directly. QEMM 5.00 and later versions
- support these four calls.
-
-
- QPI_UntrappedIORead equ 1A00h
- ; Takes AX = 1A00
- ; DX = port to read
- ; Returns BL = value read
-
-
- QPI_UntrappedIOWrite equ 1A01h
- ; Takes AX = 1A01
- ; DX = port to write
- ; BL = value to write
-
-
- QPI_UntrappedIOReadIndexed equ 1A02h
- ; Takes AX = 1A02
- ; DX = base port to read
- ; BH = index into base port
- ; Returns BL = value read
-
-
- QPI_UntrappedIOWriteIndexed equ 1A03h
- ; Takes AX = 1A03
- ; DX = base port to write
- ; BH = index into base port
- ; BL = value to write
-
-
- The QPI_UntrappedIO Call
-
- The QPI_UntrappedIO call performs the same functions as the
- QPI_UntrappedIORead and the QPI_UntrappedIOWrite calls, but it
- uses register values that are similar to the ones QEMM passes to
- your I/O callback routine (including the flags in CX that give
- information about the type and size of the I/O and the caller's
- interrupt flag). This call may therefore be easier to use from
- within an I/O callback routine. QEMM 7.03 and later support this
- call.
-
-
- QPI_UntrappedIO equ 1A04h
- ; Takes AX = 1A04
- ; BX = value to write
- ; DX = port to read or write
- ; CX = type of I/O (see description above
- ; of CX passed to callback routine)
- ; Returns BX = value read
-
- The following five calls are described in the introduction above.
- QEMM 7.03 and later versions support these calls.
-
-
- QPI_GetIOCallback equ 1A06h
- ; Takes AX = 1A06
- ; Returns ES:DI = previous I/O callback function
-
-
- QPI_SetIOCallback equ 1A07h
- ; Takes AX = 1A07
- ; ES:DI = new I/O callback function
-
-
- QPI_GetPortTrap equ 1A08h
- ; Takes AX = 1A08
- ; DX = I/O port number
- ; Returns BL = 0 if port not trapped,
- BL = 1 if port already trapped
-
-
- QPI_SetPortTrap equ 1A09h
- ; Takes AX = 1A09
- ; DX = I/O port number
-
-
- QPI_ClearPortTrap equ 1A0Ah
- ; Takes AX = 1A0A
- ; DX = I/O port number
-
-
- The QPI_SimulateHWInt Call
-
- The QPI_SimulateHWInt call can be used by callback routines that
- wish to simulate a hardware interrupt. When DESQview or DESQview/X
- is running, the interrupt handler that should receive the
- interrupt may be in a different process from the current one. Use
- QPI_SimulateHWInt to simulate an interrupt properly when DESQview
- or DESQview/X is running. The DESQview API Reference Manual
- describes how to determine when DESQview is running. QEMM 7.03 and
- later versions support this call.
-
- QPI_SimulateHWInt equ 1C04h
- ; Takes AX = 1C04
- ; BX = interrupt number to generate
-
-
- The QPI Get Sub-Version String Call
-
- QPI_Get_QEMM_SubVer equ 1E05h
-
- ; Takes AX = 1E05
- ; CX = Length of buffer
- ; ES:DI = buffer
- ; Returns CX = number of bytes which could not fit in buffer
- ; CY if function not supported
- ; Fills in the given buffer with a null terminated string. If
- ; the actual length of the string is greater than the length of
- ; the buffer (as passed in CX) then it clips the string to the
- ; buffer length - 1 and puts a null in the last byte of the buffer
- ; and returns the number of extra bytes in CX. If everything
- ; fits in the buffer, then the returned CX=0.
-
- ******************************************************************
- * Trademarks are property of their respective owners. *
- * This and other technical notes may be available in updated *
- * forms through Quarterdeck's standard support channels. *
- * Copyright (C) 1995 Quarterdeck Corporation *
- ******************** E N D O F F I L E ***********************
-
-